package com.service.sys;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.base.BaseConstant;
import com.common.base.BaseService;
import com.entity.sys.SysMenu;
import com.entity.sys.SysRoleMenu;
import com.mapper.sys.SysMenuMapper;
import com.mapper.sys.SysRoleMenuMapper;
import fuhua.com.util.RedisUtil;
import fuhua.com.util.TreeUtil;
import fuhua.com.vo.MetaVo;
import fuhua.com.vo.RouterVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单权限表 服务实现类
 */
@Service
public class SysMenuService extends BaseService<SysMenuMapper, SysMenu>{

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    /**
     * 根据角色id查询菜单
     */
    public List<SysMenu> selectPermsByRoleId(Map<String,String> map){
        sysParams(map);
        return baseMapper.selectPermsByRoleId(map);
    }

    /**
     * 查询系统菜单列表
     */
    public List<SysMenu> selectMenuList(Map<String,String> map) {
        List<SysMenu> menuList = null;
        if (StrUtil.isEmpty(map.get("id"))){
            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
            if (StrUtil.isNotBlank(map.get("name"))) {
                queryWrapper.like("name", map.get("name"));
            }
            if (StrUtil.isNotBlank(map.get("state"))) {
                queryWrapper.eq("state", map.get("state"));
            }
            queryWrapper.orderByAsc("parent_id,sort");
            menuList = baseMapper.selectList(queryWrapper);
        }else {
            sysParams(map);
            menuList = baseMapper.selectMenuListByRoleId(map);
        }
        return menuList;
    }

    /**
     * 根据角色id查询菜单树
     */
    public List<SysMenu> selectMenuTreeByRoleId(Map<String,String> map) {
        sysParams(map);
        List<SysMenu> menus = baseMapper.selectMenuTreeByRoleId(map);
        return TreeUtil.buildTreeIsRoot(menus,"ROOT");
    }

    /**
     * 构建前端路由所需要的菜单
     */
    public List<RouterVo> buildMenus(List<SysMenu> menus) {
        List<RouterVo> routers = new LinkedList<>();
        for (SysMenu menu : menus) {
            RouterVo router = new RouterVo();
            router.setHidden(menu.getVisible());
            router.setName(StrUtil.upperFirst(menu.getPath()));
            router.setPath(getRouterPath(menu));
            router.setComponent(menu.getUrl());
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon(),menu.getActiveMenu()));
            List<SysMenu> cMenus = menu.getChildren();
            if (!cMenus.isEmpty() && "M".equals(menu.getType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildMenus(cMenus));
            }else if ("C".equals(menu.getType()) && "0".equals(menu.getParentId())){
                List<RouterVo> childrenList = new ArrayList<>();
                RouterVo children = new RouterVo();
                children.setName(StrUtil.upperFirst(menu.getPath()));
                children.setPath(menu.getPath());
                children.setComponent(menu.getUrl());
                children.setMeta(new MetaVo(menu.getName(), menu.getIcon(),menu.getActiveMenu()));
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 是否存在菜单子节点
     */
    public boolean hasChildByMenuId(String id) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",id);
        int result = baseMapper.selectCount(queryWrapper);
        return result > 0 ? true : false;
    }

    /**
     * 查询菜单使用数量
     */
    public boolean checkMenuExistRole(String id) {
        QueryWrapper<SysRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("menu_id",id);
        int result = sysRoleMenuMapper.selectCount(queryWrapper);
        return result > 0 ? true : false;
    }

    /**
     * 校验菜单名称是否唯一
     */
    public boolean checkMenuNameUnique(SysMenu menu) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        String id = StrUtil.isBlank(menu.getId()) ? "-1" : menu.getId();
        queryWrapper.eq("name",menu.getName());
        queryWrapper.eq("parent_id",menu.getParentId());
        SysMenu info = baseMapper.selectOne(queryWrapper);
        if (info != null && !info.getId().equals(id)) {
            return true;
        }
        return false;
    }

    /**
     * 根据角色id查询菜单id列表
     */
    public List<String> selectIdListByRoleId(Map<String,String> map){
        List<String> idList = new ArrayList<>();
        List<SysMenu> menus = selectPermsByRoleId(map);
        for (SysMenu m : menus) {
            idList.add(m.getId());
        }
        return idList;
    }

    /**
     * 获取路由地址
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = menu.getPath();
        if ("M".equals(menu.getType())) {
            if (!BaseConstant.PARENT_VIEW.equals(menu.getUrl())){
                routerPath = "/" + menu.getPath();
            }
        }else if ("C".equals(menu.getType()) && "0".equals(menu.getParentId())){
            routerPath = "/";
        }
        return routerPath;
    }

    /**
     * 改了角色与权限关联时，更新redis中的角色与权限关联
     */
    public void updateRolePerm(String roleId){
        Map<String,String> query = new HashMap<>();
        query.put("id",roleId);
        List<SysMenu> menuList = selectPermsByRoleId(query);
        List<String> permList = menuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());
        RedisUtil.hset(BaseConstant.rolePermList,roleId,permList);
    }

    /**
     * 修改菜单，改了菜单的权限标识时，更新redis中的权限标识
     */
    public void updatePerm(String oldPerm,String newPerm){
        Map<String, Object> map = RedisUtil.hmget(BaseConstant.rolePermList);
        for (String key : map.keySet()) {
            List<String> permList = (List<String>) map.get(key);
            int index = permList.indexOf(oldPerm); // 获取旧权限标识的索引
            if (index != -1){
                permList.set(index,newPerm); // 更新新标识
            }
        }
        RedisUtil.hmset(BaseConstant.rolePermList,map);
    }

    /**
     * 删除角色时，删除redis中的角色与权限关联
     */
    public void deleteRolePerm(String roleId){
        RedisUtil.hdel(BaseConstant.rolePermList,roleId);
    }
}
